package de.justphil.tcg.tcgserver.game.mechanics.property.properties;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.List;

import de.justphil.tcg.tcgserver.game.mechanics.event.Event;
import de.justphil.tcg.tcgserver.game.mechanics.game.Attack;
import de.justphil.tcg.tcgserver.game.mechanics.game.Game;
import de.justphil.tcg.tcgserver.game.mechanics.game.GameDataSerializable;
import de.justphil.tcg.tcgserver.game.mechanics.monster.Monster;
import de.justphil.tcg.tcgserver.game.mechanics.monster.MonsterList;
import de.justphil.tcg.tcgserver.game.mechanics.property.Property;

public class AttackDamageReflection extends Property implements GameDataSerializable {

	public AttackDamageReflection(Game game) {

		super(game);
	}
	
	private int preAttackDamage = 0;

	@Override
	public int getType() {

		return PROPERTY_ATTACK_DAMAGE_REFLECTION;
	}

	@Override
	protected MonsterList handleEvent(Event event) {

		int eventType = event.getType();

		switch (eventType) {

		case Event.EVENT_ATTACK_FINISHED:

			MonsterList monsters = new MonsterList();
			monsters.add(handleAttackFinished((Attack) event.getData()));
			return monsters;

		case Event.EVENT_ATTACK_INVOKED:

			handleAttackInvoked((Attack) event.getData());
			return null;

		default:
			assert false;
			return null;
		}
	}

	@Override
	protected List<Integer> getListeningEventTypes() {

		List<Integer> types = super.getListeningEventTypes();
		types.add(Event.EVENT_ATTACK_FINISHED);
		types.add(Event.EVENT_ATTACK_INVOKED);

		return types;
	}

	private Monster handleAttackFinished(Attack attack) {

		Monster monster = getMonster();

		if (attack.getTarget().equals(monster)) {

			int damage = monster.getProperties(PROPERTY_DAMAGE).size()
					- preAttackDamage;

			for (int i = 0; i < damage; i++) {

				provideProperty(attack.getAttacker(), PROPERTY_DAMAGE);
			}
			if (damage > 0) {
				return attack.getAttacker();
			}
		}
		return null;
	}

	private void handleAttackInvoked(Attack attack) {

		Monster monster = getMonster();

		if (attack.getTarget().equals(monster)) {

			preAttackDamage = monster.getProperties(PROPERTY_DAMAGE).size();
		}
	}

	@Override
	public void writeData(Game game, DataOutput out) throws IOException {
		super.writeData(game, out);
		out.writeInt(preAttackDamage);
	}

	@Override
	public void readData(Game game, DataInput in) throws IOException {
		super.readData(game, in);
		preAttackDamage = in.readInt();
	}
}
